<!--
 * @Author: 杨有财
 * @Date: 2025-03-01 20:30:05
 * @LastEditTime: 2025-03-01 21:29:35
 * @LastEditors: 杨有财
 * @Description: 表格组件
-->
<template>
  <t-table
    :class="{ 'comp-table': maxHeight === '100%' }"
    :size="size"
    :show-header="showHeader"
    :stripe="stripe"
    :cell-empty-content="cellEmptyContent"
    :max-height="maxHeight"
    :bordered="bordered"
    :data="data"
    :columns="columns"
    :row-key="rowKey"
    :hover="hover"
    :pagination="pagination"
    :selected-row-keys="selectedRowKeys"
    :table-layout="tableLayout"
    :table-content-width="tableContentWidth"
    :resizable="resizable"
    :show-sort-column-bg-color="showSortColumnBgColor"
    :hide-sort-tips="hideSortTips"
    :sort="sort"
    :loading="loading"
    @page-change="handlePageChange"
    @select-change="handleSelectChange"
    @change="handleChange"
    @sort-change="handleSortChange"
  >
    <template v-for="slotName in columnsList" #[slotName.colKey]="{ row, rowIndex }">
      <slot :name="slotName.colKey" :row="row" :row-index="rowIndex">{{
        utils.valueFormat(row[slotName.colKey])
      }}</slot>
    </template>
  </t-table>
</template>
<script setup lang="ts">
import { uniqBy } from 'lodash';
import { BaseTableCol, SizeEnum, SortInfo, TableProps } from 'tdesign-vue-next';

import utils from '@/utils';

defineOptions({
  name: 'CommonTable',
});
const {
  data,
  columns,
  rowKey,
  hover,
  pagination,
  bordered,
  loading,
  cellEmptyContent,
  maxHeight,
  size,
  showHeader,
  stripe,
  tableLayout,
  tableContentWidth,
  resizable,
  showSortColumnBgColor,
  hideSortTips,
  sort,
} = defineProps({
  data: {
    required: true,
    type: Array as PropType<TableProps['data']>,
    default: (): TableProps['data'] => [],
  },
  columns: {
    required: true,
    type: Array as PropType<BaseTableCol[]>,
    default: (): BaseTableCol[] => [],
  },
  // 必需。唯一标识一行数据的字段名
  rowKey: {
    type: String,
    default: 'id',
  },
  // 是否显示鼠标悬浮状态
  hover: {
    type: Boolean,
    default: true,
  },
  // 分页配置，值为空则不显示
  pagination: {
    type: Object as PropType<TableProps['pagination']>,
    default(): TableProps['pagination'] {
      return null;
    },
  },
  // 选中行，控制属性。半选状态行请更为使用
  selectedRowKeys: {
    type: Array as PropType<TableProps['selectedRowKeys']>,
    default(): TableProps['selectedRowKeys'] {
      return [];
    },
  },
  // 加载中状态
  loading: {
    type: Boolean,
    default: undefined,
  },
  // 单元格数据为空时呈现的内容
  cellEmptyContent: {
    type: String,
    default: '--',
  },
  // 是否显示表格边框
  bordered: {
    type: Boolean,
    default: false,
  },
  // 表格最大高度，超出后会出现滚动条。示例：100, '30%', '300'。值为数字类型，会自动加上单位 px
  maxHeight: {
    type: [String, Number],
    default: '100%',
  },
  // 是否显示斑马纹
  stripe: {
    type: Boolean,
    default: false,
  },
  // 是否显示表头
  showHeader: {
    type: Boolean,
    default: true,
  },
  // 表格尺寸。可选项：small/medium/large。
  size: {
    type: String as PropType<SizeEnum>,
    default: 'medium',
  },
  // 表格布局方式，<table> 元素原生属性 注意，在列宽调整下场景只能使用 fixed 模式。
  tableLayout: {
    type: String as PropType<'fixed' | 'auto'>,
    default: 'fixed',
  },
  tableContentWidth: {
    type: String,
    default: '',
  },
  // 是否允许调整当前列列宽
  resizable: {
    type: Boolean,
    default: false,
  },
  // 当前排序列是否显示背景色
  showSortColumnBgColor: {
    type: Boolean,
    default: false,
  },
  // 隐藏排序文本提示，支持全局配置
  hideSortTips: {
    type: Boolean,
    default: false,
  },
  // 序控制。sortBy 排序字段；descending 是否进行降序排列。
  sort: {
    type: [Object, Array] as PropType<SortInfo>,
    default() {
      return {};
    },
  },
});

const columnsList = ref<BaseTableCol[]>([]);
const emit = defineEmits(['change', 'sort-change', 'page-change', 'select-change']);

watch(
  () => columns,
  () => {
    formatColumns();
  },
);

const formatColumns = () => {
  if (columns.length > 0) {
    columns.forEach((item) => {
      if (item.ellipsis) {
        item.ellipsis = typeof item.ellipsis === 'boolean' ? { theme: 'light' } : { ...item.ellipsis, theme: 'light' };
      } else {
        item.ellipsis = {
          theme: 'light',
          placement: 'top-left',
        };
      }
    });
    // @ts-ignore
    columnsList.value = columns.filter((item) => item.colKey !== 'row-select');
  }
};
// 整理columns数据
formatColumns();

const handleChange: TableProps['onChange'] = (data, context) => {
  emit('change', data, context);
};
// 排序发生变化时触发。其中 sortBy 表示当前排序的字段，sortType 表示排序的方式
const handleSortChange: TableProps['onSortChange'] = (sort, options) => {
  emit('sort-change', sort, options);
};
const handlePageChange: TableProps['onPageChange'] = (pageInfo, newDataSource) => {
  emit('page-change', pageInfo, newDataSource);
};
const handleSelectChange: TableProps['onSelectChange'] = (selectedRowKeys, options) => {
  const selectedData = ref([]);
  const rowData = ref([]);
  // 重新整理selectedRowData数据，解决取消全选时数据为空的bug
  const { selectedRowData, type, currentRowData } = options;
  if (type === 'check') {
    selectedData.value.push(...selectedRowData);
    // 去重存入数组的数据
    selectedData.value = uniqBy(selectedData.value, rowKey);
  }
  if (selectedRowKeys.length > 0) {
    rowData.value = selectedData.value.filter((item) => {
      if (item) {
        return selectedRowKeys.includes(item[rowKey]);
      }
      return [];
    });
  } else {
    selectedData.value = [];
  }

  emit('select-change', selectedRowKeys, { selectedRowData: rowData.value, type, currentRowData });
};
</script>

<style lang="less" scoped>
:deep(.t-table__empty) {
  flex-direction: column;
  margin-bottom: 40px;
}

.comp-table {
  margin-top: 10px;

  :deep(thead) {
    z-index: 0;
  }

  :deep(th) {
    background-color: #f2f3f5 !important;
    color: #39485d;
    font-weight: 600;
  }
}
</style>
